#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "cracker.h"
#include "genpasswd.h"
#include "aes.h"
#include "util.h"

#define DICTIONARY_FILE "files/common_passwords.txt"

static FILE * dict= NULL;
static int d_index= -1;

int
crack(char * file, User ** users, int count)
{
	int cracked=0, i=0;
	int file_len;
	char * secret;
	char * passwd;
	
	passwd= calloc(1, 128);
	
	/* open encrypted file */
	file_len = readfile(file, &secret, FILE_SIZE);

	/* try decryption for all users */
	while (i != count && !cracked)
	{
		reset_counter();
		while ( !cracked && nextpass(passwd) )
			cracked = tryPass(users[i], passwd, secret, file_len);
		i++;
	}
	if( cracked )
		printf("Password found: '%s'\n", passwd);
	free(passwd);
	free(secret);
	return cracked;
}

int
nextpass(char * pass)
{
	int len;
	char aux[128];

	if( d_index++ == -1 )
	{
		if( !dict && (dict = fopen(DICTIONARY_FILE, "rb")) == NULL )
		{
			printf("No se pudo abrir el archivo diccionario.\n");
			exit(1);
		}
		if( fgets(pass, INT_MAX, dict) == NULL )
			return 0;
		pass[strlen(pass)-1]= '\0';
		return 1;
	}
	len= strlen(pass);
	if( d_index == 1 )
	{
		pass[len]= '0'+d_index;
		pass[len+1]= '\0';
	}
	else if( d_index < 10 )
	{
		pass[len-1]= '0'+d_index;
		pass[len]= '\0';
	}
	else if( d_index == 10 )
	{
		pass[len-1]= '\0';
		aux[0]= '0';
		aux[1]= '\0';
		strcat(aux, pass);
		strcpy(pass, aux);
	}
	else
		pass[0]= '0'+(d_index-10);
	if( d_index == 19 )
		d_index= -1;
	return 1;
}

void
reset_counter()
{
	if( dict )
		fclose(dict);
	dict= NULL;
	d_index= -1;
	return;
}

int
tryPass(User *user, char *word, char *secret, int secretLen)
{
    int i;
    int found = 0;
    unsigned char hash[SHA_DIGEST_LENGTH];
    char buffer[80] = {0};
    char vuelcoEnBytes[KEY_SIZE] = {0};
	
    if ( user == NULL || word == NULL || secret == NULL )
        return found;
	
    strcpy(buffer, user->name);
    strcat(buffer, word);
    calculateHash(hash, buffer);
	
    hex2byte((unsigned char *)vuelcoEnBytes, user->key, KEY_SIZE);

    for ( i=0 ; i < 16 ; i++ )
    {
        hash[i] ^= vuelcoEnBytes[i];
    }
	
    for ( i = 16 ; i < SHA_DIGEST_LENGTH ; i++)
    {
        hash[i] = 0;
    }
	
	byte2hex(buffer, hash, 16);
    found = decryptAES(secret, secretLen, (char *)hash);
	
    return found;
}
